package com.hospital.hospitalserver.service;

import com.hospital.hospitalserver.entity.PatientRegistrationRequest;
import com.hospital.hospitalserver.entity.PatientVisitDTO;
import com.hospital.hospitalserver.entity.PaymentMainDTO;
import com.hospital.hospitalserver.entity.ScheduleInstanceDTO;
import com.hospital.hospitalserver.entity.Vo.ScheduleInstance;
import com.hospital.hospitalserver.enums.ResultCodeEnum;
import com.hospital.hospitalserver.exception.CustomException;
import com.hospital.hospitalserver.mapper.RegistrationMapper;
import com.hospital.hospitalserver.mapper.ScheduleInstanceMapper;
import com.hospital.hospitalserver.util.Response;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

/**
 * 挂号缴费操作实现类
 * */
@Service
@RequiredArgsConstructor
public class RegistrationService {
    private final RegistrationMapper registrationMapper;
    private final ScheduleInstanceMapper scheduleInstanceMapper;

    /**
     * 提交挂号信息（未缴费）
     * 添加事务处理，执行有错误回滚操作
     */
    @Transactional(rollbackFor = Exception.class)
    public Response registrationAdd(PatientRegistrationRequest request) {
        try {
            // 1. 检查挂号编号是否已存在
            Integer exists = registrationMapper.checkAppointmentIdExists(
                    request.getPatientVisitDTO().getAppointment_id()
            );
            if (exists > 0) {
                throw new RuntimeException("挂号编号已存在");
            }

            // 2. 添加患者挂号就诊表基础信息
            PatientVisitDTO patientVisit = request.getPatientVisitDTO();
            patientVisit.setVisit_status("registered");
            patientVisit.setCreate_time(LocalDateTime.now());
            patientVisit.setUpdate_time(LocalDateTime.now());

            Integer patientCount = registrationMapper.addPatientVisit(patientVisit);
            if (patientCount <= 0) {
                throw new RuntimeException("添加患者就诊记录失败");
            }

            // 3. 设置收费记录的就诊ID
            PaymentMainDTO paymentMain = request.getPaymentMainDTO();
            paymentMain.setVisit_id(patientVisit.getVisit_id()); // 设置关联的visit_id
            paymentMain.setSource_id(patientVisit.getVisit_id()); // 设置来源ID为就诊ID

            // 4. 检查支付单号是否已存在
            exists = registrationMapper.checkPaymentNoExists(paymentMain.getPayment_no());
            if (exists > 0) {
                throw new RuntimeException("支付单号已存在");
            }

            // 5. 添加收费表主表信息
            paymentMain.setPayment_status("pending");
            paymentMain.setCreate_time(LocalDateTime.now());
            paymentMain.setUpdate_time(LocalDateTime.now());

            Integer paymentCount = registrationMapper.addPaymentMain(paymentMain);
            if (paymentCount <= 0) {
                throw new RuntimeException("添加收费记录失败");
            }

            return Response.success("挂号信息提交成功，请完成支付");

        } catch (Exception e) {
            throw new RuntimeException("挂号信息提交失败: " + e.getMessage(), e);
        }
    }

    /**
     * 缴费修改挂号缴费状态
     * 添加事务处理，执行有错误回滚操作
     */
    @Transactional(rollbackFor = Exception.class)
    public Response completePayment(PatientRegistrationRequest request) {
        try {
            PaymentMainDTO paymentMain = request.getPaymentMainDTO();

            if (paymentMain == null) {
                throw new RuntimeException("支付信息不能为空");
            }

            // 验证支付单号是否存在
            PaymentMainDTO existingPayment = registrationMapper.getPaymentByPaymentNo(paymentMain.getPayment_no());
            if (existingPayment == null) {
                throw new RuntimeException("支付单不存在: " + paymentMain.getPayment_no());
            }

            // 更新收费状态为已收费
            paymentMain.setPayment_status("completed");
            paymentMain.setPayment_time(LocalDateTime.now());
            paymentMain.setUpdate_time(LocalDateTime.now());
            paymentMain.setPaid_amount(paymentMain.getActual_amount()); // 设置已支付金额

            // 更新收费记录
            Integer updateCount = registrationMapper.updatePaymentStatus(paymentMain);
            if (updateCount == null || updateCount <= 0) {
                // 自定义错误信息
                throw new CustomException(ResultCodeEnum.SYSTEM_ERROR,"更新收费状态失败，支付单号: " + paymentMain.getPayment_no());
            }

            // 收费成功后，同时更新就诊状态
            PatientVisitDTO patientVisit = request.getPatientVisitDTO();
            if (patientVisit != null && patientVisit.getAppointment_id() != null) {
                // 验证就诊记录是否存在
                PatientVisitDTO existingVisit = registrationMapper.getVisitByAppointmentId(patientVisit.getAppointment_id());
                if (existingVisit == null) {
                    throw new CustomException(ResultCodeEnum.SYSTEM_ERROR,"就诊记录不存在: " + patientVisit.getAppointment_id());
                }

                patientVisit.setVisit_status("registered");
                patientVisit.setUpdate_time(LocalDateTime.now());

                Integer visitUpdateCount = registrationMapper.updateVisitStatus(patientVisit);
                if (visitUpdateCount == null || visitUpdateCount <= 0) {
                    throw new CustomException(ResultCodeEnum.SYSTEM_ERROR,"更新就诊状态失败，挂号编号: " + patientVisit.getAppointment_id());
                }
            }

            // 收费成功更新当前医生当天的排班中的可挂号数
            // 获取当前排班实例数据，取出max_patients，actual_patients进行更新
            Integer schedule_instance_id = patientVisit.getSchedule_instance_id();
            ScheduleInstance scheduleInstanceData = scheduleInstanceMapper.getScheduleInstanceDataByScheduleId(schedule_instance_id);
            Integer max_patients = scheduleInstanceData.getMax_patients();
            Integer actual_patients = scheduleInstanceData.getActual_patients();
            //判断当前最大挂号数不为零
            if(max_patients>actual_patients){
                actual_patients +=1;
            }else {
                throw new CustomException(ResultCodeEnum.ERROR,"挂号数已满，请选择其他医生");
            }
            ScheduleInstanceDTO scheduleInstanceDTO = new ScheduleInstanceDTO();
            scheduleInstanceDTO.setInstance_id(schedule_instance_id);
            scheduleInstanceDTO.setMax_patients(max_patients);
            scheduleInstanceDTO.setActual_patients(actual_patients);
            //执行更新
            scheduleInstanceMapper.updateScheduleInstances(scheduleInstanceDTO);


            return Response.success("缴费成功");

        } catch (Exception e) {
            throw new CustomException(ResultCodeEnum.SYSTEM_ERROR,"缴费失败: " + e.getMessage());
        }
    }
}
